package com.le.tester.utils;

import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;


@Slf4j
public class ListUtils {


    /**
     * lambda表达式对两个List进行循环,根据符合条件,进行相关的赋值操作并返回这个对象集合
     *
     * @param sourceList   待设置源列表
     * @param srcEqualProp 源对象条件判断属性名
     * @param srcSetProp   源对象待设置属性名
     * @param targetList   资源提供者列表
     * @param tarEqualProp 对象条件判断参数名
     * @param tarGetProp   待获取对象属性名
     * @param <T>
     * @param <U>
     * @return
     */
    public static <T, U> List<T> setListByEqualObjProperty(List<T> sourceList, String srcEqualProp, String srcSetProp,
                                                           List<U> targetList, String tarEqualProp, String tarGetProp) {
        List<T> resultList = Lists.newArrayList();
        resultList = sourceList.stream()
                .map(sur -> targetList.stream()
                        .filter(tar -> Objects.equals(getValueByPropName(sur, srcEqualProp), getValueByPropName(tar, tarEqualProp)))
                        .findFirst()
                        .map(tar -> {
                            setValueByPropName(sur, srcSetProp, getValueByPropName(tar, tarGetProp));
                            return sur;
                        }).orElse(null))
                .collect(Collectors.toList());

        return resultList;
    }

    /**
     * 通过遍历两个List中按id属性相等的归结到resultList中
     *
     * @param oneList      源list 1
     * @param twoList      源list 2
     * @param equalKeyName 相等的map键值
     */
    public static List<Map<Object, Object>> compareListHitData(List<Map<Object, Object>> oneList, List<Map<Object, Object>> twoList, Object equalKeyName) {
        return oneList.stream().map(map -> twoList.stream()
                .filter(m -> Objects.equals(m.get(equalKeyName), map.get(equalKeyName)))
                .findFirst().map(m -> {
                    map.putAll(m);
                    return map;
                }).orElse(null))
                .filter(Objects::nonNull).collect(Collectors.toList());
    }


    // 通过属性获取传入对象的指定属性的值
    public static <T> T getValueByPropName(Object object, String propName) {
        T value = null;
        try {
            // 通过属性获取对象的属性
            Field field = object.getClass().getDeclaredField(propName);
            // 对象的属性的访问权限设置为可访问
            field.setAccessible(true);
            // 获取属性的对应的值
            value = (T) field.get(object);
        } catch (Exception e) {
            return null;
        }

        return value;
    }

    // 通过属性设置传入对象的指定属性的值
    public static <U> void setValueByPropName(Object object, String propName, U updateValue) {

        try {
            // 通过属性获取对象的属性
            Field field = object.getClass().getDeclaredField(propName);
            // 对象的属性的访问权限设置为可访问
            field.setAccessible(true);
            // 设置属性的对应的值
            field.set(object, updateValue);
        } catch (Exception e) {
            log.error("setValueByPropName.error {}", propName, e);
        }


    }


}
